using System;
using System.Collections.Generic;
using System.Text;

namespace CodePlex.Resourceful
{
    public class ReadOnlyList<T> : IEnumerable<T>
    {
        public static readonly ReadOnlyList<T> Empty = new ReadOnlyList<T>(new T[0]);

        private readonly List<T> _values;

        public ReadOnlyList(IEnumerable<T> values)
        {
            _values = new List<T>(values);
        }

        public bool Contains(T item)
        {
            return _values.Contains(item);
        }
        public T Find(Predicate<T> match)
        {
            return _values.Find(match);
        }

        public ReadOnlyList<T> FindAll(Predicate<T> match)
        {
            return new ReadOnlyList<T>(_values.FindAll(match));
        }

        public ReadOnlyList<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter)
        {
            return new ReadOnlyList<TOutput>(_values.ConvertAll(converter));
        }

        public T[] ToArray()
        {
            return _values.ToArray();
        }

        public int IndexOf(T value)
        {
            return _values.IndexOf(value);
        }

        public ReadOnlyList<T> Sort(Comparison<T> comparison)
        {
            List<T> rt = new List<T>(_values);

            rt.Sort(comparison);
            return new ReadOnlyList<T>(rt);
        }

        public ReadOnlyList<T> Top(int limit)
        {
            limit = limit > _values.Count ? _values.Count : limit;
            limit = limit < 0 ? 0 : limit;

            List<T> rt = new List<T>(limit);
            for (int i = 0; i < limit; i++)
            {
                rt.Add( _values[i]);
            }
            
            return new ReadOnlyList<T>(rt);
        }

        public int Count
        {
            get
            {
                return _values.Count;
            }
        }

        public T this[int index]
        {
            get
            {
                return _values[index];
            }
        }

        public IEnumerator<T> GetEnumerator()
        {
            return _values.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _values.GetEnumerator();
        }


        public bool Exists(Predicate<T> match)
        {
            return _values.Exists(match);
        }

    }









    public class ReadOnlyList<T,X> : ReadOnlyList<T>
    {

        private readonly Converter<T, X> _indexFunction;

        public ReadOnlyList(IEnumerable<T> values, Converter<T, X> indexFunction)
            : base(values)
        {
            _indexFunction = indexFunction;
        }

        public T this[X index]
        {
            get
            {
                return this.Find(delegate(T item)
                {
                    return index.Equals(_indexFunction(item));
                });
            }
        }

        public bool Exists(X index)
        {
            return this.Exists(delegate(T item)
            {
                return index.Equals(_indexFunction(item));
            });
        }
    }
    
}
